/* 
 * Copyright (c)	Insighten Intelligent Equipment co.,LTD
 * 
 *  Use of this software is controlled by the terms and conditions found
 *  in the license agreement under which this software has been supplied.
 * 
 */
/** 
 * @file sock_util.c
 * @brief 
 * @author taco [tacoee@gmail.com]
 * @version 0.1
 * @date 2010-09-03
 */

#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <string.h>

#include "sock_util.h"
#include "types.h"

int set_sock_opt(int fd, SocketAttr *attr)
{
	int opt;
	int len;
	int ret = -1;

	if (fd == -1 ||
			attr == NULL ) {
		return RET_FAIL;
	}

	opt = 1;
	ret = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (void *)&opt, sizeof(opt));
	if (ret < 0) {
		/*need to add log here*/
	}
	if (!attr->blocking) {
		fcntl(fd, F_SETFL, O_NONBLOCK);
	}
	len = sizeof(opt);
	ret = getsockopt(fd, SOL_SOCKET, SO_SNDBUF,&opt, &len);
	if (ret < 0) {
		/*need to add log here*/
	} else {
		if (opt < attr->sock_buf_size) {
			ret = setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &attr->sock_buf_size,
					sizeof(attr->sock_buf_size));
			if (ret < 0) {
				/*need to add log here*/
			}
		}
	}

	return RET_OK;
}

struct in_addr net_get_ip(char *ifname)
{
	struct ifreq ifr;
	int skfd;

	if ( (skfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0 ) {
		return (struct in_addr) {-1};
	}

	strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
	if (ioctl(skfd, SIOCGIFADDR, &ifr) < 0) {
		return (struct in_addr){-1};
	}

	close(skfd);
	return ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr;
}

Ret net_set_ifaddr(char *ifname, in_addr_t addr)
{
	struct ifreq ifr;
	int skfd;
	struct sockaddr_in sa;

	if ( (skfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0 ) {
		return RET_FAIL;
	}
	sa.sin_addr.s_addr = addr;
	strncpy(ifr.ifr_name, ifname, strlen(ifname));
	memcpy((char *) &ifr.ifr_addr, (char *) &sa, sizeof(struct sockaddr));
	if (ioctl(skfd, SIOCSIFADDR, &ifr) < 0) {
		close(skfd);
		return RET_FAIL;
	}
	close(skfd);

	return RET_OK;
}
